from django.shortcuts import render, redirect
import re
from django.core.urlresolvers import reverse
from apps.user.models import User, Address
from apps.goods.models import GoodsSKU
from django.views.generic import View
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, SignatureExpired
from django.conf import settings
from django.http import HttpResponse
from celery_tasks.tasks import send_register_active_email
from django.contrib.auth import authenticate, login, logout
from utils.mixin import LoginRequiredMixin
from django_redis import get_redis_connection
from apps.order.models import OrderInfo, OrderGoods
from django.core.paginator import Paginator


# Create your views here.

# def register(request):
#     """注册"""
#     if request.method == 'GET':
#         return render(request, 'register.html')
#     else:
#         """进行注册处理"""
#         # 接收数据
#         user_name = request.POST.get('user_name')
#         pwd = request.POST.get('pwd')
#         email = request.POST.get('email')
#         allow = request.POST.get('allow')
#         # 进行数据的校验
#         if not all([user_name, pwd, email]):
#             # 数据不完整
#             return render(request, 'register.html', {'errmsg': '数据不完整'})
#         # 校验邮箱
#         if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
#             return render(request, 'register.html', {'errmsg': '邮箱格式不正确'})
#         if allow != 'on':
#             return render(request, 'register.html', {'errmsg': '请同意协议'})
#         # 校验用户名是否重复
#         try:
#             user = User.objects.get(username=user_name)
#         except User.DoesNotExist:
#             # 用户名不存在
#             user = None
#         if user:
#             # 用户名已存在
#             return render(request, 'register.html', {'errmsg': '用户名已存在'})
#         # 业务处理
#         # user = User()
#         # user.username = user_name
#         # user.password = pwd
#         # user.email = email
#         # user.save()
#         user = User.objects.create_user(user_name, email, pwd)
#         user.is_active = 0
#         user.save()
#         # 返回应答,跳转到首页
#         # 通过reverse实现动态url的匹配
#         return redirect(reverse('goods:index'))


# def register_handle(request):
#     """进行注册处理"""
#     # 接收数据
#     user_name = request.POST.get('user_name')
#     pwd = request.POST.get('pwd')
#     email = request.POST.get('email')
#     allow = request.POST.get('allow')
#     # 进行数据的校验
#     if not all([user_name, pwd, email]):
#         # 数据不完整
#         return render(request, 'register.html', {'errmsg': '数据不完整'})
#     # 校验邮箱
#     if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
#         return render(request, 'register.html', {'errmsg': '邮箱格式不正确'})
#     if allow != 'on':
#         return render(request, 'register.html', {'errmsg': '请同意协议'})
#     # 校验用户名是否重复
#     try:
#         user = User.objects.get(username=user_name)
#     except User.DoesNotExist:
#         # 用户名不存在
#         user = None
#     if user:
#         # 用户名已存在
#         return render(request, 'register.html', {'errmsg': '用户名已存在'})
#     # 业务处理
#     # user = User()
#     # user.username = user_name
#     # user.password = pwd
#     # user.email = email
#     # user.save()
#     user = User.objects.create_user(user_name, email, pwd)
#     user.is_active = 0
#     user.save()
#     # 返回应答,跳转到首页
#     # 通过reverse实现动态url的匹配
#     return redirect(reverse('goods:index'))


class RegisterView(View):
    """注册类视图"""

    def get(self, request):
        """显示注册页面"""
        return render(request, 'register.html')

    def post(self, request):
        """进行注册处理"""
        # 接收数据
        user_name = request.POST.get('user_name')
        pwd = request.POST.get('pwd')
        email = request.POST.get('email')
        allow = request.POST.get('allow')
        # 进行数据的校验
        if not all([user_name, pwd, email]):
            # 数据不完整
            return render(request, 'register.html', {'errmsg': '数据不完整'})
        # 校验邮箱
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return render(request, 'register.html', {'errmsg': '邮箱格式不正确'})
        if allow != 'on':
            return render(request, 'register.html', {'errmsg': '请同意协议'})
        # 校验用户名是否重复
        try:
            user = User.objects.get(username=user_name)
        except User.DoesNotExist:
            # 用户名不存在
            user = None
        if user:
            # 用户名已存在
            return render(request, 'register.html', {'errmsg': '用户名已存在'})
        # 业务处理
        # user = User()
        # user.username = user_name
        # user.password = pwd
        # user.email = email
        # user.save()
        user = User.objects.create_user(user_name, email, pwd)
        user.is_active = 0
        user.save()

        # 发送激活邮件,包含激活链接http://127.0.0.1:8000/user/active/3
        serializer = Serializer(settings.SECRET_KEY, 3600 * 2)
        info = {'confirm': user.id}
        # 将info信息加密
        token = serializer.dumps(info)  # bytes
        token = token.decode('utf8')
        # 模拟发送邮件这里点击邮件的链接直接打印出来
        print('http://127.0.0.1:8000/user/active/%s' % token)

        """
        subject = '生鲜网店欢迎信息'
        message = ''
        sender = settings.EMAIL_FROM
        receiver = [email]
        html_message = '<h1>%s,欢迎您成为生鲜网店的会员</h1>请点击以下链接激活您的账户:<br/><a href="http://127.0.0.1:8000/user/active/%s">http://127.0.0.1:8000/user/active/%s</a>' % (
            user_name, token, token)
        send_mail(subject, message, sender, receiver, html_message=html_message)
        """

        # 使用celery开启任务发邮件
        send_register_active_email.delay(email, user_name, token)

        # 返回应答,跳转到首页
        # 通过reverse实现动态url的匹配
        return redirect(reverse('user:login'))


class ActiveView(View):
    """激活视图类"""

    def get(self, request, token):
        """去激活"""
        serializer = Serializer(settings.SECRET_KEY, 3600 * 2)
        try:
            info = serializer.loads(token)
            id = info['confirm']
            user = User.objects.get(id=id)
            user.is_active = 1
            user.save()
            return redirect(reverse('user:login'))
        except SignatureExpired as e:
            return HttpResponse('激活链接已过期')


class LoginView(View):
    """登录视图类"""

    def get(self, request):
        """显示登录界面"""
        # 判断是否记住了用户名
        if 'username' in request.COOKIES:
            username = request.COOKIES.get('username')
            checked = 'checked'
        else:
            username = ''
            checked = ''
        # 使用模板
        return render(request, 'login.html', {'username': username, 'checked': checked})

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('pwd')

        if not all([username, password]):
            # 数据不完整
            return render(request, 'login.html', {'errmsg': '数据不完整'})

        # 业务处理:登录校验
        user = authenticate(username=username, password=password)
        if user is not None:
            # 用户名密码正确
            if user.is_active:
                # 用户已激活
                # 记录用户的登录状态
                login(request, user)

                # 获取登录后跳转的地址
                # url = request.GET.get('next')
                # if url == None:
                #     url = reverse('goods:index')
                url = request.GET.get('next', reverse('goods:index'))
                # 跳转到首页
                response = redirect(url)  # HttpResponseRedirect

                # 判断是否需要记住用户名
                remember = request.POST.get('remember')

                if remember == 'on':
                    # 记住用户名
                    response.set_cookie('username', username, max_age=7 * 24 * 3600)
                else:
                    response.delete_cookie('username')

                # 返回response
                return response
            else:
                # 用户未激活
                return render(request, 'login.html', {'errmsg': '账户未激活'})
        else:
            # 用户名或密码错误
            return render(request, 'login.html', {'errmsg': '用户名或密码错误'})


class LogoutView(View):
    """退出登录视图"""

    def get(self, request):
        """退出登录"""
        # 清除用户的session信息
        logout(request)
        # 跳转到首页
        return redirect(reverse('goods:index'))


class UserInfoView(LoginRequiredMixin, View):
    """用户中心信息页"""

    def get(self, request):
        """显示"""
        # page = 'user'
        # request.user.is_authenticated()
        # 用户未登录->AnonymousUser-->is_authenticated()返回False
        # 如果用户登录->User类的一个实例-->is_authenticated()返回True

        # 获取用户的个人信息
        user = request.user
        address = Address.objects.get_default_address(user)
        # 获取用户的历史浏览信息
        # 链接redis
        # from redis import StrictRedis
        # sr = StrictRedis(host='localhost',port=6379,db=9)
        con = get_redis_connection('default')

        history_key = 'history_%d' % user.id

        # 获取用户最新浏览的5个商品的id
        sku_ids = con.lrange(history_key, 0, 4)

        # 从数据库中查询用户浏览的商品的具体信息
        # goods_li = GoodsSKU.objects.filter(id__in=sku_ids)
        # goods_res  = []
        # for a_id in sku_ids:
        #     for goods in goods_li:
        #         if a_id == goods.id:
        #             goods_res.append(goods)
        goods_res = []
        for id in sku_ids:
            goods = GoodsSKU.objects.get(id=id)
            goods_res.append(goods)

        # 组织上下文
        context = {'page': 'user',
                   'address': address,
                   'goods_res': goods_res}

        # 除了你给模板文件传递的模板变量外,django框架会把request.user也传给模板文件
        return render(request, 'user_center_info.html', context)


class UserOrderView(LoginRequiredMixin, View):
    """用户订单信息页"""

    def get(self, request, page):
        """显示"""
        # page = 'order'
        # 获取用户的订单信息
        user = request.user
        orders = OrderInfo.objects.filter(user=user).order_by('-create_time')

        # 遍历获取订单商品的信息
        for order in orders:
            # 根据order_id查询订单商品信息
            order_skus = OrderGoods.objects.filter(order_id=order.order_id)

            # 遍历order_skus计算商品的小计
            for order_sku in order_skus:
                # 计算小计
                amount = order_sku.count * order_sku.price
                # 动态给order_sku添加amount,保存订单的小计
                order_sku.amount = amount

            # 动态给order增加属性,保存订单状态标题
            order.status_name = OrderInfo.ORDER_STATUS[order.order_status]

            # 动态给order增加order_skus属性,保存订单信息
            order.order_skus = order_skus

        # 分页
        paginator = Paginator(orders, 1)

        # 获取第page页的内容
        try:
            page = int(page)
        except Exception as e:
            page = 1

        if page > paginator.num_pages:
            page = 1

        # 获取第page页的Page实例对象
        order_page = paginator.page(page)

        # 进行页码的控制，页面上最多显示5个页码
        # 1.总页数小于等于五页,显示所有页码
        # 2.总页数大于五页
        #   a.如果当前页是前3页,显示1-5页
        #   b.如果当前页码是后3页,显示后5页
        #   c.其他情况,显示当前页的前2页,当前页,当前页的而后2页
        num_pages = paginator.num_pages
        if num_pages <= 5:
            pages = range(1, num_pages + 1)
        else:
            if page <= 3:
                pages = range(1, 6)
            elif page >= num_pages - 2:
                pages = range(num_pages - 4, num_pages + 1)
            else:
                pages = range(num_pages - 2, num_pages + 3)

        # 组织上下文
        content = {'order_page': order_page,
                   'pages': pages,
                   'page': 'order'
                   }

        return render(request, 'user_center_order.html', content)


class UserSiteView(LoginRequiredMixin, View):
    """用户地址信息页"""

    def get(self, request):
        """显示"""
        # page = 'address'
        # 获取用户的默认收货地址
        # 获取登录的用户对应的User对象
        user = request.user
        # try:
        #     address = Address.objects.get(user=user, is_default=True)
        # except Address.DoesNotExist:
        #     # 不存在默认收货地址
        #     address = None
        """使用模型管理类封装的方法获取用户默认的收货地址"""
        address = Address.objects.get_default_address(user)
        return render(request, 'user_center_site.html', {'page': 'address', 'address': address})

    def post(self, request):
        """地址添加"""
        # 接收数据
        receiver = request.POST.get('receiver')
        addr = request.POST.get('addr')
        zip_code = request.POST.get('zip_code')
        phone = request.POST.get('phone')
        # 校验数据
        if not all([receiver, addr, phone]):
            return render(request, 'user_center_site.html', {'errmsg': '数据不完整!'})
        # 校验手机号
        if not re.match(r'^1[3|4|5|7|8][0-9]{9}$', phone):
            return render(request, 'user_center_site.html', {'errmsg': '手机号格式不正确!'})
        # 业务处理: 添加地址
        # 如果用户已存在默认收货地址,添加的地址不作为默认添加地址,否则作为收货地址
        # 获取登录的用户对应的User对象
        user = request.user
        # try:
        #     address = Address.objects.get(user=user, is_default=True)
        # except Address.DoesNotExist:
        #     # 不存在默认收货地址
        #     address = None
        """使用模型管理类封装的方法获取用户默认的收货地址"""
        address = Address.objects.get_default_address(user)

        if address:
            is_default = False
        else:
            is_default = True
        # 添加地址
        Address.objects.create(user=user,
                               receiver=receiver,
                               addr=addr,
                               zip_code=zip_code,
                               phone=phone,
                               is_default=is_default)
        # 返回应答,刷新地址页面
        return redirect(reverse('user:site'))  # get请求方式
